package zhuyun.code.launcheractivity.view.widget.component

import android.graphics.Rect
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlin.math.max

/**
 * @author: Administrator
 * @date: 2021/12/11
 */
class FlowLayoutManager:RecyclerView.LayoutManager() {
    class Item(val view: View,val useHeight:Int,val rect: Rect)
    class Row(var lineTop:Int = 0,var maxLineHeight:Int = 0,val views:MutableList<Item> = mutableListOf())
    private val lineRows = mutableListOf<Row>()
    override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
        return RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT)
    }
    var row = Row()
    var totalHeight = 0
    override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
        var curLineWidth = 0//不包括paddiing
        var curLineTop = paddingLeft//包括padding
        var usedMaxWidth = width - paddingLeft - paddingRight
        var maxLineHeight:Int = 0
        lineRows.clear()
        removeAllViews()
        for(i in 0 until itemCount){
            val child = recycler!!.getViewForPosition(i)
            if(i == 0){
                val layoutParams = child.layoutParams as RecyclerView.LayoutParams
                layoutParams.leftMargin = 0
                child.layoutParams = layoutParams
            }
            measureChildWithMargins(child, 0, 0)
            var childWidth = getDecoratedMeasuredWidth(child)
            val childHeight = getDecoratedMeasuredHeight(child)
            if(curLineWidth + childWidth <= usedMaxWidth){//如果当前行空间够用
                val itemLeft = paddingLeft + curLineWidth
                val itemTop = curLineTop
                val frame = Rect(itemLeft,itemTop,itemLeft+childWidth,itemTop+childHeight)
                val item = Item(child,childHeight,frame)
                row.views.add(item)
                maxLineHeight = max(maxLineHeight,childHeight)
                curLineWidth += childWidth
            } else {//不够用
                childWidth = getDecoratedMeasuredWidth(child)
                row.maxLineHeight = maxLineHeight
                totalHeight += maxLineHeight
                row.lineTop = curLineTop
                formatAboveRow()
                lineRows.add(row)
                row = Row()
                curLineTop += maxLineHeight
                val itemLeft = paddingLeft
                val itemTop = curLineTop
                val frame = Rect(itemLeft,itemTop,itemLeft+childWidth,itemTop+childHeight)
                val item = Item(child,childHeight,frame)
                row.views.add(item)
                maxLineHeight = childHeight
                curLineWidth = childWidth
            }
            if(i == itemCount -1){
                row.maxLineHeight = maxLineHeight
                totalHeight += maxLineHeight
                row.lineTop = curLineTop
                formatAboveRow()
                lineRows.add(row)
            }
        }
        fillLayout(recycler,state)
    }
    //格式化上一行
    private fun formatAboveRow(){
        //取出上一行的items
        val views = row.views
        //遍历views
        for(view in views){
            if(view.rect.top < row.lineTop + (row.maxLineHeight - view.useHeight)/2){
                view.rect.set(view.rect.left,row.lineTop-(row.maxLineHeight - view.useHeight)/2,view.rect.right
                    ,row.lineTop-(row.maxLineHeight - view.useHeight)/2)
            }
        }
    }

    private fun fillLayout(recycler: RecyclerView.Recycler?, state: RecyclerView.State?){
        if(state!!.isPreLayout){
            return
        }
        //屏幕显示范围
        val displayFrame = Rect(paddingLeft,verticalScrollOffset + paddingTop,width - paddingRight,verticalScrollOffset + height - paddingBottom)
        for(row in lineRows){
            val lineTop = row.lineTop
            val lineBottom = lineTop + row.maxLineHeight
            if(lineTop > displayFrame.top&&lineBottom < displayFrame.bottom){
                for(item in row.views){
                    val scrap = item.view
                    measureChildWithMargins(scrap, 0, 0)
                    addView(scrap)
                    val frame = item.rect
                    layoutDecoratedWithMargins(scrap,frame.left,frame.top - verticalScrollOffset, frame.right, frame.bottom - verticalScrollOffset)
                }
            } else {
                for(item in row.views){
                    val scrap = item.view
                    removeAndRecycleView(scrap,recycler!!)
                }
            }
        }
    }

    private var verticalScrollOffset = 0

    override fun canScrollVertically(): Boolean {
        return true
    }

    override fun scrollVerticallyBy(
        dy: Int,
        recycler: RecyclerView.Recycler?,
        state: RecyclerView.State?
    ): Int {
        var travel = dy
        if(verticalScrollOffset + dy < 0){
            travel = -verticalScrollOffset
        } else if(verticalScrollOffset + dy > totalHeight - getVerticalSpace()){
            travel = totalHeight - getVerticalSpace() - verticalScrollOffset
        }
        verticalScrollOffset += travel
        offsetChildrenVertical(-travel)
        fillLayout(recycler,state)
        return travel
    }

    private fun getVerticalSpace():Int{
        return height - paddingBottom - paddingTop
    }


}